package com.example.fasttransfer.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;

@RestController
@RequestMapping("/file")
public class FileUploadController {

    @Value("${file.upload-dir}")
    private String uploadDir;

    @Value("${file.temp-dir}")
    private String tempDir;

    @Value("${file.expiration-time}")
    private int expirationTime; // 文件保留时间（分钟）

    // 上传分块
    @PostMapping("/uploadChunk")
    public ResponseEntity<?> uploadChunk(@RequestParam("file") MultipartFile file,
                                         @RequestParam("chunkIndex") int chunkIndex,
                                         @RequestParam("fileId") String fileId) throws IOException {
        File tempDirectory = new File(tempDir + "/" + fileId);
        if (!tempDirectory.exists()) {
            tempDirectory.mkdirs();
        }

        // 保存分块
        File chunkFile = new File(tempDirectory, "chunk" + chunkIndex);
        file.transferTo(chunkFile);

        return ResponseEntity.ok("Chunk uploaded successfully");
    }

    // 合并所有分块
    @PostMapping("/mergeChunks")
    public ResponseEntity<?> mergeChunks(@RequestParam("fileId") String fileId) throws IOException {
        File tempDirectory = new File(tempDir + "/" + fileId);
        File[] chunks = tempDirectory.listFiles();

        if (chunks == null || chunks.length == 0) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("No chunks found to merge");
        }

        Arrays.sort(chunks); // 按文件名排序，确保顺序正确

        // 合并文件
        File outputFile = new File(uploadDir, fileId);
        File parentDir = outputFile.getParentFile();
        if (!parentDir.exists()) {
            boolean created = parentDir.mkdirs();
            if (!created) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                        .body("Failed to create upload directory: " + parentDir.getAbsolutePath());
            }
        }
        //uploadDir存在就先删除
        if (outputFile.exists()) {
            outputFile.delete();
        }

        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outputFile, true))) {
            for (File chunk : chunks) {
                try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(chunk))) {
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = bis.read(buffer)) != -1) {
                        bos.write(buffer, 0, bytesRead);
                    }
                }
            }
        }

        // 删除临时分块文件
        for (File chunk : chunks) {
            chunk.delete();
        }

        // 返回文件下载页面的 URL
        String downloadUrl = "/file/download/" + URLEncoder.encode(fileId, "UTF-8");
        return ResponseEntity.ok(downloadUrl);
    }



    @GetMapping("/download/{fileName}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String fileName) throws IOException {
        File file = new File(uploadDir + "/" + fileName);
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8");

        if (!file.exists()) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
        }

        Path filePath = file.toPath();
        // 创建 Resource 对象
        Resource resource = new FileSystemResource(filePath);

        // 获取文件类型
        String contentType = Files.probeContentType(filePath);
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType != null ? contentType : "application/octet-stream"))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + encodedFileName + "\"")
                .body(resource);
    }

}
